import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray";
import _regeneratorRuntime from "@babel/runtime/helpers/esm/regeneratorRuntime";
import _asyncToGenerator from "@babel/runtime/helpers/esm/asyncToGenerator";
import _objectWithoutProperties from "@babel/runtime/helpers/esm/objectWithoutProperties";
import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
var _excluded = ["valueEnum", "render", "renderText", "mode", "plain", "dataIndex", "request", "params", "editable"],
    _excluded2 = ["request", "columns", "params", "dataSource", "onDataSourceChange", "formProps", "editable", "loading", "onLoadingChange", "actionRef", "onRequestError"];
import { createElement as _createElement } from "react";
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { CheckOutlined, CloseOutlined, EditOutlined } from '@ant-design/icons';
import ProForm, { ProFormField } from '@ant-design/pro-form';
import ProSkeleton from '@ant-design/pro-skeleton';
import { ErrorBoundary, genCopyable, getFieldPropsOrFormItemProps, InlineErrorFormItem, LabelIconTip, useEditableMap } from '@ant-design/pro-utils';
import { ConfigProvider, Descriptions, Form, Space } from 'antd-v4';
import toArray from "rc-util/es/Children/toArray";
import get from "rc-util/es/utils/get";
import React, { useContext, useEffect } from 'react';
import { stringify } from 'use-json-comparison';
import './index.less';
import useFetchData from './useFetchData';
/**
 * 根据 dataIndex 获取值，支持 dataIndex 为数组
 *
 * @param item
 * @param entity
 */

var getDataFromConfig = function getDataFromConfig(item, entity) {
  var dataIndex = item.dataIndex;

  if (dataIndex) {
    var data = Array.isArray(dataIndex) ? get(entity, dataIndex) : entity[dataIndex];

    if (data !== undefined || data !== null) {
      return data;
    }
  }

  return item.children;
};
/**
 * 这里会处理编辑的功能
 *
 * @param props
 */


export var FieldRender = function FieldRender(props) {
  var valueEnum = props.valueEnum,
      action = props.action,
      index = props.index,
      text = props.text,
      entity = props.entity,
      mode = props.mode,
      render = props.render,
      editableUtils = props.editableUtils,
      valueType = props.valueType,
      plain = props.plain,
      dataIndex = props.dataIndex,
      request = props.request,
      renderFormItem = props.renderFormItem,
      params = props.params;
  var fieldConfig = {
    text: text,
    valueEnum: valueEnum,
    mode: mode || 'read',
    proFieldProps: {
      render: render ? function () {
        return render === null || render === void 0 ? void 0 : render(text, entity, index, action, _objectSpread(_objectSpread({}, props), {}, {
          type: 'descriptions'
        }));
      } : undefined
    },
    ignoreFormItem: true,
    valueType: valueType,
    request: request,
    params: params,
    plain: plain
  };
  /** 如果是只读模式，fieldProps 的 form是空的，所以需要兜底处理 */

  if (mode === 'read' || !mode || valueType === 'option') {
    var fieldProps = getFieldPropsOrFormItemProps(props.fieldProps, undefined, _objectSpread(_objectSpread({}, props), {}, {
      rowKey: dataIndex,
      isEditable: false
    }));
    return _jsx(ProFormField, _objectSpread(_objectSpread({
      name: dataIndex
    }, fieldConfig), {}, {
      fieldProps: fieldProps
    }));
  }

  return _jsx("div", {
    style: {
      marginTop: -5,
      marginBottom: -5,
      marginLeft: 0,
      marginRight: 0
    },
    children: _jsx(Form.Item, {
      noStyle: true,
      shouldUpdate: function shouldUpdate(pre, next) {
        return pre !== next;
      },
      children: function children(form) {
        var _editableUtils$action;

        var formItemProps = getFieldPropsOrFormItemProps(props.formItemProps, form, _objectSpread(_objectSpread({}, props), {}, {
          rowKey: dataIndex,
          isEditable: true
        }));
        var fieldProps = getFieldPropsOrFormItemProps(props.fieldProps, form, _objectSpread(_objectSpread({}, props), {}, {
          rowKey: dataIndex,
          isEditable: true
        }));
        var dom = renderFormItem ? renderFormItem === null || renderFormItem === void 0 ? void 0 : renderFormItem(_objectSpread(_objectSpread({}, props), {}, {
          type: 'descriptions'
        }), {
          isEditable: true,
          recordKey: dataIndex,
          record: form.getFieldValue([dataIndex].flat(1)),
          defaultRender: function defaultRender() {
            return _jsx(ProFormField, _objectSpread(_objectSpread({}, fieldConfig), {}, {
              fieldProps: fieldProps
            }));
          },
          type: 'descriptions'
        }, form) : undefined;
        return _jsxs(Space, {
          children: [_jsx(InlineErrorFormItem, _objectSpread(_objectSpread({
            name: dataIndex
          }, formItemProps), {}, {
            style: _objectSpread({
              margin: 0
            }, (formItemProps === null || formItemProps === void 0 ? void 0 : formItemProps.style) || {}),
            initialValue: text || (formItemProps === null || formItemProps === void 0 ? void 0 : formItemProps.initialValue),
            children: dom || _jsx(ProFormField, _objectSpread(_objectSpread({}, fieldConfig), {}, {
              // @ts-ignore
              proFieldProps: _objectSpread({}, fieldConfig.proFieldProps),
              fieldProps: fieldProps
            }))
          })), editableUtils === null || editableUtils === void 0 ? void 0 : (_editableUtils$action = editableUtils.actionRender) === null || _editableUtils$action === void 0 ? void 0 : _editableUtils$action.call(editableUtils, dataIndex || index, form, {
            cancelText: _jsx(CloseOutlined, {}),
            saveText: _jsx(CheckOutlined, {}),
            deleteText: false
          })]
        });
      }
    })
  });
};

var schemaToDescriptionsItem = function schemaToDescriptionsItem(items, entity, action, editableUtils) {
  var _items$map;

  var options = []; // 因为 Descriptions 只是个语法糖，children 是不会执行的，所以需要这里处理一下

  var children = items === null || items === void 0 ? void 0 : (_items$map = items.map) === null || _items$map === void 0 ? void 0 : _items$map.call(items, function (item, index) {
    var _getDataFromConfig, _restItem$label;

    if ( /*#__PURE__*/React.isValidElement(item)) {
      return item;
    }

    var valueEnum = item.valueEnum,
        render = item.render,
        renderText = item.renderText,
        mode = item.mode,
        plain = item.plain,
        dataIndex = item.dataIndex,
        request = item.request,
        params = item.params,
        editable = item.editable,
        restItem = _objectWithoutProperties(item, _excluded);

    var defaultData = (_getDataFromConfig = getDataFromConfig(item, entity)) !== null && _getDataFromConfig !== void 0 ? _getDataFromConfig : restItem.children;
    var text = renderText ? renderText(defaultData, entity, index, action) : defaultData;
    var title = typeof restItem.title === 'function' ? restItem.title(item, 'descriptions', null) : restItem.title; //  dataIndex 无所谓是否存在
    // 有些时候不需要 dataIndex 可以直接 render

    var valueType = typeof restItem.valueType === 'function' ? restItem.valueType(entity || {}, 'descriptions') : restItem.valueType;
    var isEditable = editableUtils === null || editableUtils === void 0 ? void 0 : editableUtils.isEditable(dataIndex || index);
    var fieldMode = mode || isEditable ? 'edit' : 'read';
    var showEditIcon = editableUtils && fieldMode === 'read' && editable !== false && (editable === null || editable === void 0 ? void 0 : editable(text, entity, index)) !== false;
    var Component = showEditIcon ? Space : React.Fragment;
    var contentDom = fieldMode === 'edit' ? text : genCopyable(text, item, text);

    var field = /*#__PURE__*/_createElement(Descriptions.Item, _objectSpread(_objectSpread({}, restItem), {}, {
      key: restItem.key || ((_restItem$label = restItem.label) === null || _restItem$label === void 0 ? void 0 : _restItem$label.toString()) || index,
      label: (title || restItem.label || restItem.tooltip || restItem.tip) && _jsx(LabelIconTip, {
        label: title || restItem.label,
        tooltip: restItem.tooltip || restItem.tip,
        ellipsis: item.ellipsis
      })
    }), _jsxs(Component, {
      children: [_jsx(FieldRender, _objectSpread(_objectSpread({}, item), {}, {
        dataIndex: item.dataIndex || index,
        mode: fieldMode,
        text: contentDom,
        valueType: valueType,
        entity: entity,
        index: index,
        action: action,
        editableUtils: editableUtils
      })), showEditIcon && valueType !== 'option' && _jsx(EditOutlined, {
        onClick: function onClick() {
          editableUtils === null || editableUtils === void 0 ? void 0 : editableUtils.startEditable(dataIndex || index);
        }
      })]
    })); // 如果类型是 option 自动放到右上角


    if (valueType === 'option') {
      options.push(field);
      return null;
    }

    return field;
  }).filter(function (item) {
    return item;
  });
  return {
    // 空数组传递还是会被判定为有值
    options: (options === null || options === void 0 ? void 0 : options.length) ? options : null,
    children: children
  };
};

var ProDescriptionsItem = function ProDescriptionsItem(props) {
  return _jsx(Descriptions.Item, _objectSpread(_objectSpread({}, props), {}, {
    children: props.children
  }));
};

var DefaultProDescriptionsDom = function DefaultProDescriptionsDom(dom) {
  return dom.children;
};

var ProDescriptions = function ProDescriptions(props) {
  var _props$editable;

  var request = props.request,
      columns = props.columns,
      _props$params = props.params,
      params = _props$params === void 0 ? {} : _props$params,
      dataSource = props.dataSource,
      onDataSourceChange = props.onDataSourceChange,
      formProps = props.formProps,
      editable = props.editable,
      loading = props.loading,
      onLoadingChange = props.onLoadingChange,
      actionRef = props.actionRef,
      onRequestError = props.onRequestError,
      rest = _objectWithoutProperties(props, _excluded2);

  var context = useContext(ConfigProvider.ConfigContext);
  var action = useFetchData( /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee() {
    var data;
    return _regeneratorRuntime().wrap(function _callee$(_context) {
      while (1) {
        switch (_context.prev = _context.next) {
          case 0:
            if (!request) {
              _context.next = 6;
              break;
            }

            _context.next = 3;
            return request(params);

          case 3:
            _context.t0 = _context.sent;
            _context.next = 7;
            break;

          case 6:
            _context.t0 = {
              data: {}
            };

          case 7:
            data = _context.t0;
            return _context.abrupt("return", data);

          case 9:
          case "end":
            return _context.stop();
        }
      }
    }, _callee);
  })), {
    onRequestError: onRequestError,
    effects: [stringify(params)],
    manual: !request,
    dataSource: dataSource,
    loading: loading,
    onLoadingChange: onLoadingChange,
    onDataSourceChange: onDataSourceChange
  });
  /*
   * 可编辑行的相关配置
   */

  var editableUtils = useEditableMap(_objectSpread(_objectSpread({}, props.editable), {}, {
    childrenColumnName: undefined,
    dataSource: action.dataSource,
    setDataSource: action.setDataSource
  }));
  /** 支持 reload 的功能 */

  useEffect(function () {
    if (actionRef) {
      actionRef.current = _objectSpread({
        reload: action.reload
      }, editableUtils);
    }
  }, [action, actionRef, editableUtils]); // loading 时展示
  // loading =  undefined 但是 request 存在时也应该展示

  if (action.loading || action.loading === undefined && request) {
    return _jsx(ProSkeleton, {
      type: "descriptions",
      list: false,
      pageHeader: false
    });
  }

  var getColumns = function getColumns() {
    // 因为 Descriptions 只是个语法糖，children 是不会执行的，所以需要这里处理一下
    var childrenColumns = toArray(props.children).filter(Boolean).map(function (item) {
      if (! /*#__PURE__*/React.isValidElement(item)) {
        return item;
      }

      var _item$props = item === null || item === void 0 ? void 0 : item.props,
          valueEnum = _item$props.valueEnum,
          valueType = _item$props.valueType,
          dataIndex = _item$props.dataIndex,
          ellipsis = _item$props.ellipsis,
          copyable = _item$props.copyable,
          itemRequest = _item$props.request;

      if (!valueType && !valueEnum && !dataIndex && !itemRequest && !ellipsis && !copyable) {
        return item;
      }

      return _objectSpread(_objectSpread({}, item === null || item === void 0 ? void 0 : item.props), {}, {
        entity: dataSource
      });
    });
    return [].concat(_toConsumableArray(columns || []), _toConsumableArray(childrenColumns)).filter(function (item) {
      if (!item) return false;

      if ((item === null || item === void 0 ? void 0 : item.valueType) && ['index', 'indexBorder'].includes(item === null || item === void 0 ? void 0 : item.valueType)) {
        return false;
      }

      return !(item === null || item === void 0 ? void 0 : item.hideInDescriptions);
    }).sort(function (a, b) {
      if (b.order || a.order) {
        return (b.order || 0) - (a.order || 0);
      }

      return (b.index || 0) - (a.index || 0);
    });
  };

  var _schemaToDescriptions = schemaToDescriptionsItem(getColumns(), action.dataSource || {}, (actionRef === null || actionRef === void 0 ? void 0 : actionRef.current) || action, editable ? editableUtils : undefined),
      options = _schemaToDescriptions.options,
      children = _schemaToDescriptions.children;
  /** 如果不是可编辑模式，没必要注入 ProForm */


  var FormComponent = editable ? ProForm : DefaultProDescriptionsDom;
  /** 即使组件返回null了, 在传递的过程中还是会被Description检测到为有值 */

  var title = null;

  if (rest.title || rest.tooltip || rest.tip) {
    title = _jsx(LabelIconTip, {
      label: rest.title,
      tooltip: rest.tooltip || rest.tip
    });
  }

  var className = context.getPrefixCls('pro-descriptions');
  return _jsx(ErrorBoundary, {
    children: _jsx(FormComponent, _objectSpread(_objectSpread({
      form: (_props$editable = props.editable) === null || _props$editable === void 0 ? void 0 : _props$editable.form,
      component: false,
      submitter: false
    }, formProps), {}, {
      onFinish: undefined,
      children: _jsx(Descriptions, _objectSpread(_objectSpread({
        className: className
      }, rest), {}, {
        extra: rest.extra ? _jsxs(Space, {
          children: [options, rest.extra]
        }) : options,
        title: title,
        children: children
      }))
    }), "form")
  });
};

ProDescriptions.Item = ProDescriptionsItem;
export { ProDescriptions };
export default ProDescriptions;